/**
 * 
 */
package javavis.jip2d.functions.tia2012;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import javax.help.NoMerge;
import javax.help.plaf.basic.BasicFavoritesNavigatorUI.AddAction;

/**
 * @author asc
 * 
 */
public class AdaBoost implements Serializable
{
    /**
     * 
     */
    /*
    public StrongLearner           clasificadorFuerte;
    public ArrayList<Feature>      H;
    public ArrayList<TrainExample> listaCaras;
    public ArrayList<TrainExample> listaNoCaras;

    public AdaBoost(ArrayList<Feature> listaCaracteristicas, ArrayList<TrainExample> listaCara, ArrayList<TrainExample> listaNoCara)
    {
        // Clasificador Fuerte.
        clasificadorFuerte = new StrongLearner();
        listaCaras = (ArrayList<TrainExample>) listaCara.clone();
        listaNoCaras = (ArrayList<TrainExample>) listaNoCara.clone();

        // Inicializamos los pesos del conjunto de entrenamiento.
        // ArrayList<TrainExample> listaEntrenamineto = new
        // ArrayList<TrainExample>();
        for (TrainExample trainExample : listaCaras)
        {
            trainExample.setPeso(1.0 / listaCaras.size());
            // listaEntrenamineto.add(trainExample);
        }

        for (TrainExample trainExample : listaNoCaras)
        {
            trainExample.setPeso(1.0 / listaNoCaras.size());
            // listaEntrenamineto.add(trainExample);
        }

        // H listaClasificadores debiles
        H = (ArrayList<Feature>) listaCaracteristicas.clone();

    }
    
    public StrongLearner AlgoritmoAdaBoost()
    {

        System.out.println(H.size() + "-" + listaCaras.size() + "-" + listaNoCaras.size());
        // T Numero Caracteristicas a seleccionar
        // int T=listaCaracteristicas.size();
        int T = 1;

        // m numero imagenes con cara
        int m = listaCaras.size();
        // n numero imagenes sin cara
        int n = listaNoCaras.size();
        // l numero imagenes
        int l = n + m;

        long time;
        long timeFinal;
        double normPesosAnterior = Double.MAX_VALUE;
        timeFinal = System.currentTimeMillis();
        for (int t = 0; t < T; t++)
        {

            // Normalizar Pesos
            System.out.println(t + "-" + T + " normalizar pesos");
            double normPesos = 0.0;
            for (TrainExample trainExample : listaCaras)
            {
                normPesos += trainExample.getPeso();
            }
            for (TrainExample trainExample : listaNoCaras)
            {
                normPesos += trainExample.getPeso();
            }
            for (TrainExample trainExample : listaCaras)
            {
                trainExample.setPeso(trainExample.getPeso() / normPesos);
            }
            for (TrainExample trainExample : listaNoCaras)
            {
                trainExample.setPeso(trainExample.getPeso() / normPesos);
            }
            System.out.println(normPesosAnterior + " - " + normPesos);
            if (normPesosAnterior == normPesos)
            {
                break;
            }
            normPesosAnterior = normPesos;
            // C numero Clasificadores

            int i = 0;
            int tam = H.size();
            long timelap = System.currentTimeMillis();
            time = System.currentTimeMillis();
            ExecutorService exec = Executors.newFixedThreadPool(8);
            for (Feature feature : H)
            {
                feature.setListaCaras(listaCaras);
                feature.setListaNoCaras(listaNoCaras);
                // feature.entrenarFeature();
                exec.execute(feature);
            }

            exec.shutdown();
            try
            {
                exec.awaitTermination(30, TimeUnit.MINUTES);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() - timelap);
            exec = null;

            int indice = 0;
            double error = Double.MAX_VALUE;
            // Buscar Clasificador con menor Error
            for (Feature feature : H)
            {
                if (feature.getError() < error)
                {
                    indice = H.indexOf(feature);
                    error = feature.getError();
                }
            }
            // Eliminar H el clasificador con menor Error
            // Actualizar los pesos de cada imagen
            // Anyadir a Clasificadores Seleccionados
            Feature temp = H.remove(indice);
            temp.recalculaPesos(listaCaras, listaNoCaras);
            System.out.println("error:" + temp.getError() + " " + temp.getUmbral());
            if (temp.getError() != 0.0) clasificadorFuerte.anadirClasificador(temp);

        }
        System.out.println("final:" + (System.currentTimeMillis() - timeFinal));
        return clasificadorFuerte;
    }
    */
    
    public StrongLearner clasificadorFuerte;
    public Feature[]      H;
    public TrainExample[] listaCaras;
    public TrainExample[] listaNoCaras;
    public static double globalError;
    
    public AdaBoost(Feature[] listaCaracteristicas, TrainExample[] listaCara, TrainExample[] listaNoCara)
    {
        // Clasificador Fuerte.
        clasificadorFuerte = new StrongLearner();
        listaCaras = listaCara.clone();
        listaNoCaras = listaNoCara.clone();

        // Inicializamos los pesos del conjunto de entrenamiento.
        // ArrayList<TrainExample> listaEntrenamineto = new
        // ArrayList<TrainExample>();
        for (TrainExample trainExample : listaCaras)
        {
            trainExample.setPeso(1.0 / listaCaras.length);
            // listaEntrenamineto.add(trainExample);
        }

        for (TrainExample trainExample : listaNoCaras)
        {
            trainExample.setPeso(1.0 / listaNoCaras.length);
            // listaEntrenamineto.add(trainExample);
        }

        // H listaClasificadores debiles
        H =listaCaracteristicas.clone();

    }

    public StrongLearner AlgoritmoAdaBoost()
    {

        // System.out.println(H.length + "-" + listaCaras.length+ "-" + listaNoCaras.length);
        // T Numero Caracteristicas a seleccionar
        // int T=listaCaracteristicas.size();
        int T = 1;
        /*
        // m numero imagenes con cara
        int m = listaCaras.length;
        // n numero imagenes sin cara
        int n = listaNoCaras.length;
        // l numero imagenes
        int l = n + m;
        */

        long timeFinal;
        timeFinal = System.currentTimeMillis();
        for (int t = 0; t < T; t++)
        {

            // Normalizar Pesos
            //System.out.println(t + "-" + T + " normalizar pesos");
            double normPesos = 0.0;
            for (TrainExample trainExample : listaCaras)
            {
                normPesos += trainExample.getPeso();
            }
            for (TrainExample trainExample : listaNoCaras)
            {
                normPesos += trainExample.getPeso();
            }
            for (TrainExample trainExample : listaCaras)
            {
                trainExample.setPeso(trainExample.getPeso() / normPesos);
            }
            for (TrainExample trainExample : listaNoCaras)
            {
                trainExample.setPeso(trainExample.getPeso() / normPesos);
            }
            
            // C numero Clasificadores

            
            long timelap = System.currentTimeMillis();
            ExecutorService exec = Executors.newFixedThreadPool(8);
            //AdaBoost.globalError = Double.MAX_VALUE -10;
            int size=H.length;
            for (int k=0; k<size; k++)
            {
                if(H[k]==null)continue;
                
                    H[k].setListaCaras(listaCaras);
                    H[k].setListaNoCaras(listaNoCaras);
                    // feature.entrenarFeature();
                    exec.execute(H[k]);
                
            }

            exec.shutdown();
            try
            {
                exec.awaitTermination(30, TimeUnit.MINUTES);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() - timelap);
            exec = null;

            int indice = 0;
            double error = Double.MAX_VALUE;
            //double error = AdaBoost.globalError;
            // Buscar Clasificador con menor Error
            for (int k=0; k<size; k++)
            {
                if (H[k]!=null && H[k].getError() < error)
                {
                    indice = k;
                    error = H[k].getError();
                }
            }
            // Eliminar H el clasificador con menor Error
            // Actualizar los pesos de cada imagen
            // Anyadir a Clasificadores Seleccionados
            Feature temp = H[indice];
            temp.recalculaPesos(listaCaras, listaNoCaras);
            System.out.println("error:" + temp.getError() + " " + temp.getUmbral());
            if (temp.getError() != 0.0) clasificadorFuerte.anadirClasificador(temp);
            H[indice]=null;

        }
        System.out.println("final:" + (System.currentTimeMillis() - timeFinal));
        return clasificadorFuerte;
    }
    
    
}
